
package com.csc775.message;

/**
 * This class provide methods for creating control message 
 * which is to be communicated between client and server.
 * 
 * @author pkulkar
 */


import java.io.Serializable;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.StringTokenizer;

public class ControlMessage implements Serializable {
	private static final String LOG_TAG = null;
	ControlPacket localPack;

	/**
	 * This is the constructor of class.
	 * @param destinationIP
	 * @param destinationPort
	 * @param lengthOfExtraData
	 * @param extraData
	 */
	public ControlMessage(String destinationIP, int destinationPort,
			int lengthOfExtraData, String extraData) {
		try {
			localPack = new ControlPacket();
			localPack.setDestinationIP(destinationIP);
			localPack.setDestinationPort(destinationPort);
			localPack.setSourceIP(getLocalIpAddress());
			//localPack.setDestinationIP(InetAddress.getLocalHost().getHostAddress());
			localPack.setSourcePort(destinationPort);
			localPack.setExtraData(extraData);
			localPack.setLengthOfExtraData(lengthOfExtraData);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * This returns Control pack info
	 * @return
	 */
	public ControlPacket getControlPacket() {
		return localPack;
	}

	/**
	 * Provide the local IP address of the system 
	 * @return
	 */
	public String getLocalIpAddress() {
		try {
			for (Enumeration<NetworkInterface> en = NetworkInterface
					.getNetworkInterfaces(); en.hasMoreElements();) {
				NetworkInterface intf = en.nextElement();
				for (Enumeration<InetAddress> enumIpAddr = intf
						.getInetAddresses(); enumIpAddr.hasMoreElements();) {
					InetAddress inetAddress = enumIpAddr.nextElement();
					if (!inetAddress.isLoopbackAddress()) {
						return inetAddress.getHostAddress().toString();
					}
				}
			}
		} catch (SocketException ex) {
			//Log.e(LOG_TAG, ex.toString());
		}
		return null;
	}

	/**
	 * Return server's IP
	 * @return
	 */
	public String getServerIp() {
		String address = null;
		try {
			address = InetAddress.getLocalHost().getHostAddress().toString();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return address;
	}

	/**
	 * This will set request type to joun group
	 */
	public void joinGroup() {
		try {
			localPack.setRequestType(ControlRquestType.JOIN);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	/**
	 * This will set request type to leave 
	 */
	public void leave() {
		try {
			localPack.setRequestType(ControlRquestType.LEAVE);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void leaveAck() {
		try {
			localPack.setRequestType(ControlRquestType.LEAVE_ACK);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public void displayControlMessage() {
		localPack.displayControlPacket();
	}

	public int getLengthOfExtraData() {
		return localPack.getLengthOfExtraData();
	}

	public String getExtraData() {
		return localPack.getExtraData();
	}

	public int getRequestType() {
		return localPack.getRequestType();
	}

	public String getSourceIP() {
		return localPack.getSourceIP();
	}

	public int getSourcePort() {
		return localPack.getSourcePort();
	}

	public String getDestinationIP() {
		return localPack.getDestinationIP();
	}

	public int getDestinationPort() {
		return localPack.getDestinationPort();
	}

	public void setRequestType(int val) {
		try {
			localPack.setRequestType(val);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/** 
	 * This method will convert the object data in to a string 
	 * format which can be then sent over the network
	 */
	@Override
	public String toString() {
		StringBuffer buf = new StringBuffer();
		buf.append("messageType ControlMessage ");
		buf.append(" destinationIP ");
		buf.append(localPack.getDestinationIP());
		buf.append(" destinationPort ");
		buf.append(localPack.getDestinationPort());
		buf.append(" sourceIP ");
		buf.append(localPack.getSourceIP());
		buf.append(" sourcePort ");
		buf.append(localPack.getSourcePort());
		buf.append(" requestType ");
		buf.append(localPack.getRequestType());
		buf.append(" extraData ");
		buf.append(localPack.getExtraData());
		return buf.toString();
	}

	/**
	 * On the receieving of the string send over the netrwork from onde node,
	 * we can create control message object using this method
	 * @param str
	 * @return
	 */
	public static ControlMessage getControlMessageInstance(String str) {
		StringTokenizer tok = new StringTokenizer(str);
		String destinationIP = null, sourceIP = null, extraData = null;
		int destinationPort = -1, sourcePort = -1, score = -1, request = -1;
		while (tok.hasMoreTokens()) {
			String name = tok.nextToken();
			if (name.equals("destinationIP"))
				destinationIP = tok.nextToken();

			else if (name.equals("destinationPort"))
				destinationPort = (Integer.parseInt(tok.nextToken()));
			else if (name.equals("sourceIP")) {
				sourceIP = tok.nextToken();
			} else if (name.equals("sourcePort"))
				sourcePort = (Integer.parseInt(tok.nextToken()));
			else if (name.equals("requestType"))
				request = (Integer.parseInt(tok.nextToken()));
			else if (name.equals("extraData"))
				extraData = tok.nextToken().toString();
			else {
				tok.nextElement();

			}
		}
		ControlMessage obj = new ControlMessage(destinationIP, destinationPort,
				extraData.length(), extraData);
		obj.setRequestType(request);
		obj.getControlPacket().setSourceIP(sourceIP);
		obj.getControlPacket().setSourcePort(sourcePort);
		return obj;
	}
	
}

